/*
* Copyright (c) 2009-2010, EzWare All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.Redistributions in binary
* form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided
* with the distribution.Neither the name of the EzWare nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.ezware.dialog.task.design;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Set;
import java.util.UUID;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import net.miginfocom.swing.MigLayout;
import com.ezware.common.Icons;
import com.ezware.common.Markup;
import com.ezware.common.Strings;
import com.ezware.dialog.task.IContentDesign;
import com.ezware.dialog.task.TaskDialog;
public class TaskDialogContent extends JPanel implements TaskDialog.Details, TaskDialog.Footer {
private static final long serialVersionUID = 1L;
final JLabel lbIcon = hidden(new JLabel());
final JLabel lbInstruction = hidden(new JLabel());
final JLabel lbText = hidden(new JLabel());
final JPanel pExpandable = hidden(new JPanel(new BorderLayout()));
final JPanel pComponent = hidden(new JPanel(new BorderLayout()));
final DetailsToggleButton cbDetails = hidden(new DetailsToggleButton());
final JCheckBox cbFooterCheck = hidden(new JCheckBox());
final JLabel lbFooter = hidden(new JLabel());
final JPanel pCommands = new JPanel(new MigLayout("ins 0, nogrid, fillx, aligny 100%, gapy unrel"));
final JPanel pFooter = hidden(new JPanel(new MigLayout()));
final JPanel pCommandPane = new JPanel(new MigLayout());
private final String[] detailsText = new String[2];
private String instruction = null;
private String text;
private boolean alwaysExpanded;
private static <T extends JComponent> T hidden(T c) {
c.setVisible(false);
return c;
}
public TaskDialogContent() {
pExpandable.setOpaque(false);
pComponent.setOpaque(false);
cbDetails.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
final boolean selected = e.getStateChange() == ItemEvent.SELECTED;
cbDetails.setText(selected ? getExpandedLabel() : getCollapsedLabel());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
pExpandable.setVisible(selected);
SwingUtilities.getWindowAncestor(TaskDialogContent.this).pack();
}
});
}
});
}
public void setInstruction(String instruction) {
this.instruction = instruction;
boolean visible = instruction != null && instruction.trim().length() > 0;
lbInstruction.setVisible(visible);
if (visible)
lbInstruction.setText(Markup.toHTML(instruction));
}
public String getInstruction() {
return instruction;
}
public void setCommands(Set<? extends TaskDialog.Command> commands, boolean lockButtonSize) {
pCommands.removeAll();
String group = lockButtonSize ? "sgx commands, " : "";
TaskDialog owner = getOwner();
for (final TaskDialog.Command c : commands) {
String tag = c.getTag() == null ? "" : c.getTag().toString();
pCommands.add(new JButton(new CommandAction(c, owner)), group + "aligny top, " + tag);
}
}
public boolean isCommandsVisible() {
return pCommandPane.isVisible();
}
public void setCommandsVisible(boolean visible) {
pCommandPane.setVisible(visible);
}
public void setMainText(String text) {
this.text = text;
boolean isEmtpy = Strings.isEmpty(text);
lbText.setText(Markup.toHTML(text));
lbText.setVisible(!isEmtpy);
}
public String getMainText() {
return text;
}
private TaskDialog getOwner() {
return TaskDialog.getInstance(this);
}
@Override
public String getCollapsedLabel() {
return Strings.isEmpty(detailsText[0]) ? getOwner().getString(UIManager.getString(IContentDesign.TEXT_MORE_DETAILS))
: detailsText[0];
}
@Override
public void setCollapsedLabel(String collapsedLabel) {
detailsText[0] = collapsedLabel;
}
@Override
public String getExpandedLabel() {
return Strings.isEmpty(detailsText[1]) ? getOwner().getString(UIManager.getString(IContentDesign.TEXT_FEWER_DETAILS))
: detailsText[1];
}
@Override
public void setExpandedLabel(String expandedLabel) {
detailsText[1] = expandedLabel;
}
@Override
public JComponent getExpandableComponent() {
return pExpandable.getComponentCount() == 0 ? null : (JComponent) pExpandable.getComponent(0);
}
@Override
public void setExpandableComponent(JComponent c) {
pExpandable.removeAll();
if (c != null)
pExpandable.add(c);
cbDetails.setVisible(c != null && !alwaysExpanded);
}
@Override
public boolean isExpanded() {
return cbDetails.isSelected();
}
@Override
public void setExpanded(boolean expanded) {
cbDetails.setSelected(!expanded);
cbDetails.setSelected(expanded);
pExpandable.setVisible(expanded);
}
@Override
public void setAlwaysExpanded(boolean alwaysExpanded) {
if (alwaysExpanded) {
setExpanded(true);
}
cbDetails.setVisible(getExpandableComponent() != null && !alwaysExpanded);
this.alwaysExpanded = alwaysExpanded;
}
@Override
public boolean isAlwaysExpanded() {
return alwaysExpanded;
}
@Override
public String getCheckBoxText() {
return cbFooterCheck.getText();
}
private Icon icon;
public void setMainIcon(Icon icon) {
lbIcon.setVisible(icon != null);
lbIcon.setIcon(icon);
}
public Icon getMainIcon() {
return lbIcon.getIcon();
}
@Override
public Icon getIcon() {
return icon;
}
@Override
public void setIcon(Icon icon) {
this.icon = icon; // stored to preserve actual size
lbFooter.setIcon(Icons.scale(icon, 16, 16));
}
@Override
public String getText() {
return lbFooter.getText();
}
@Override
public void setText(String text) {
boolean footerLabelVisible = !Strings.isEmpty(text);
pFooter.setVisible(footerLabelVisible);
lbFooter.setVisible(footerLabelVisible);
lbFooter.setText(Markup.toHTML(text));
}
public void setComponent(JComponent c) {
pComponent.removeAll();
if (c != null)
pComponent.add(c);
pComponent.setVisible(c != null);
}
public JComponent getComponent() {
return pComponent.getComponentCount() == 0 ? null : (JComponent) pComponent.getComponent(0);
}
@Override
public boolean isCheckBoxSelected() {
return cbFooterCheck.isVisible() && cbFooterCheck.isSelected();
}
@Override
public void setCheckBoxSelected(boolean selected) {
cbFooterCheck.setSelected(selected);
}
@Override
public void setCheckBoxText(String text) {
cbFooterCheck.setVisible(!Strings.isEmpty(text));
cbFooterCheck.setText(text == null ? "" : text);
}
class CommandAction extends AbstractAction implements TaskDialog.ValidationListener {
private static final long serialVersionUID = 1L;
private final TaskDialog.Command command;
private final TaskDialog dlg;
private Timer timer;
private int counter;
public CommandAction(TaskDialog.Command command, TaskDialog dlg) {
super(dlg.getString(command.getTitle()));
this.command = command;
this.dlg = dlg;
this.counter = command.getWaitInterval();
// setup default keystrokes
KeyStroke keyStroke = command.getKeyStroke();
if (keyStroke != null) {
String actionID = "TaskDialog.Command." + UUID.randomUUID().toString();
TaskDialogContent.this.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(keyStroke, actionID);
TaskDialogContent.this.getActionMap().put(actionID, this);
}
dlg.addValidationListener(this);
putValue(Action.NAME, getTitle());
if (counter > 0) {
setEnabled(false);
timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tick();
}
});
dlg.addPropertyListener("visible", new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent e) {
if (Boolean.TRUE.equals(e.getNewValue())) {
timer.start();
}
}
});
}
}
@Override
public void validationFinished(boolean validationResult) {
setEnabled(command.isEnabled(validationResult));
}
@Override
public void actionPerformed(ActionEvent e) {
dlg.setResult(command);
if (command.isClosing())
dlg.setVisible(false);
}
private String getTitle() {
String title = dlg.getString(command.getTitle());
return counter > 0 ? String.format("%s (%d)", title, counter) : title;
}
private void tick() {
if (--counter <= 0) {
timer.stop();
}
putValue(Action.NAME, getTitle());
setEnabled(counter <= 0);
}
}
}